import logging
import hashlib
import os
from fastapi import APIRouter, File, UploadFile, HTTPException, Depends, Request
from app.utils.request_utils import get_user_params  # 导入全局方法
from app.utils.response_utils import build_response
from app.utils.tasks import process_upload_task
from app.controllers.upload_controller import apply_file_upload_lease, create_ai_upload_file_record
import time
from app.database.db_setup import get_db
from sqlalchemy.orm import Session

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

upload_router = APIRouter()

# 允许的文件类型
ALLOWED_FILE_TYPES = {"pdf", 'docx'}
# 最大文件大小（这里设置为 100MB）
MAX_FILE_SIZE = 100 * 1024 * 1024

# 定义文件保存的目录，使用时间戳作为子目录名
UPLOAD_DIR = f"uploads/{int(time.time())}"
os.makedirs(UPLOAD_DIR, exist_ok=True)


async def validate_file(file: UploadFile = File(...)):
    file_ext = file.filename.split(".")[-1].lower()
    if file_ext not in ALLOWED_FILE_TYPES:
        logger.error(f"不允许的文件类型: {file_ext}，文件名: {file.filename}")
        raise HTTPException(status_code=400, detail=f"不允许的文件类型，仅支持 {', '.join(ALLOWED_FILE_TYPES)}")
    content = await file.read()
    file.file.seek(0)
    if len(content) > MAX_FILE_SIZE:
        logger.error(f"文件大小超过限制: {len(content)} 字节，文件名: {file.filename}")
        raise HTTPException(status_code=400, detail=f"文件大小不能超过 {MAX_FILE_SIZE / (1024 * 1024)} MB")
    return file


async def calculate_file_md5(file: UploadFile):
    hash_object = hashlib.sha256()  # 使用更安全的SHA256算法
    for chunk in iter(lambda: file.file.read(4096), b""):
        hash_object.update(chunk)
    file.file.seek(0)  # 重置文件指针
    return hash_object.hexdigest()


async def save_file_to_server(file: UploadFile):
    """
    将文件保存到服务器本地目录
    :param file: 上传的文件对象
    :return: 保存后的文件路径
    """
    file_path = os.path.join(UPLOAD_DIR, file.filename)
    try:
        with open(file_path, "wb") as buffer:
            buffer.write(await file.read())
        logger.info(f"文件成功保存到服务器，文件路径: {file_path}，文件名: {file.filename}")
        return file_path
    except Exception as e:
        logger.error(f"保存文件到服务器时出错: {e}，文件名: {file.filename}")
        return None


@upload_router.post("/upload/")
async def upload(
    request: Request,
    file: UploadFile = File(...),
    db: Session = Depends(get_db)
):
    params = await get_user_params(request)
    category_id = params.get("category_id")
    cat_id = params.get("cat_id")
    script_id = params.get("script_id")
    if not category_id:
        logger.error("CategoryId 为空")
        return build_response(100, '分类不能为空')
    if not script_id:
        return build_response(100, '归属话术不能为空')
    try:
        validated_file = await validate_file(file)
        size_in_bytes = len(await validated_file.read())  # 获取文件大小
        validated_file.file.seek(0)  # 重置文件指针
        md5 = await calculate_file_md5(validated_file)  # 获取文件 MD5 值
        file_name = file.filename  # 获取文件名称

        logger.info(f"开始上传文件，CategoryId: {category_id}，文件大小: {size_in_bytes} 字节，MD5: {md5}，文件名: {file_name}")

        file_path = await save_file_to_server(validated_file)
        if file_path:
            # 获取 add_time
            add_time = int(time.time())
            absolute_file_path = os.path.abspath(file_path)
            try:
                # 调用封装的方法创建数据库记录
                new_record = create_ai_upload_file_record(
                    script_id=script_id,
                    md5=md5,
                    cat_id=cat_id,
                    CategoryId=category_id,
                    is_set=0,  # 假设初始为未导入状态，可根据实际修改
                    size_in_bytes=size_in_bytes,
                    file_path=file_path,
                    file_name=file_name,
                    absolute_file_path=absolute_file_path,
                    add_time=add_time,  # 获取文件创建时间作为添加时间，可按需调整
                    db=db
                )
                print(f"new_record 方法创建的新分类: {new_record}")
            except Exception as e:  # 修改异常变量名
                logger.error(f"数据库操作出错: {str(e)}")
                return build_response(100, "数据库操作失败，请稍后重试", {"error_detail": str(e)})
            process_upload_task.send(md5, cat_id, category_id, file_name, size_in_bytes, absolute_file_path, new_record.id)

            return build_response(200, '成功')
        else:
            return build_response(100, "文件保存到服务器失败，请稍后重试", {})

    except FileNotFoundError as e:
        logger.error(f"文件未找到，CategoryId: {category_id}, 错误信息: {str(e)}")
        return build_response(100, "文件未找到", {"error_detail": str(e)})
    except PermissionError as e:
        logger.error(f"没有权限访问文件，CategoryId: {category_id}, 错误信息: {str(e)}")
        return build_response(100, "没有权限访问文件", {"error_detail": str(e)})
    except Exception as e:
        logger.error(f"文件上传过程中出现未知错误，CategoryId: {category_id}, 错误信息: {e}")
        return build_response(100, "文件上传过程中出现未知错误，请稍后重试", {"error_detail": str(e)})